package dashboard

import (
	log "aggregation/collector/logger"
	model "aggregation/model/dashboard"
	"aggregation/store"
	"aggregation/store/postgres"
	"context"
	"sort"
	"time"
)

// 按照时间排序生成
func convertToCount(sqlCounts postgres.DurationCounts) (counts []int64) {
	// 先按照时间排序从前到后
	counts = make([]int64, len(sqlCounts))
	sort.Sort(sqlCounts)
	for i, sqlCount := range sqlCounts {
		counts[i] = sqlCount.Count
	}
	return counts
}

// 主要是计算环比同比，波浪图
func dayIncrease(ctx context.Context, timePoint time.Time, cache store.ICache, sql store.ICounter) model.Comparison {
	day := time.Date(timePoint.Year(), timePoint.Month(), timePoint.Day(), 0, 0, 0, 0, timePoint.Location())
	onDay := time.Date(timePoint.Year(), timePoint.Month()-1, timePoint.Day(), 0, 0, 0, 0,
		timePoint.Location())
	overDay := time.Date(timePoint.Year(), timePoint.Month(), timePoint.Day()-1, 0, 0, 0, 0,
		timePoint.Location())
	count, _ := sql.CountByRange(ctx, day, day.Add(24*time.Hour))
	// 同比的数据无需检查
	onCount, _ := sql.CountByRange(ctx, onDay, onDay.Add(24*time.Hour))
	// 触发更新本月数据(不包含昨天)
	overCount, _ := sql.CountByRange(ctx, overDay, overDay.Add(24*time.Hour))
	return model.Comparison{
		Num:      count.Count,
		OnRate:   calculateRate(count.Count, onCount.Count),
		OverRate: calculateRate(count.Count, overCount.Count),
	}
}

func monthIncrease(ctx context.Context, timePoint time.Time, cache store.ICache, sql store.ICounter) model.Comparison {
	month := time.Date(timePoint.Year(), timePoint.Month(), 1, 0, 0, 0, 0, timePoint.Location())
	onMon := time.Date(timePoint.Year()-1, timePoint.Month(), 1, 0, 0, 0, 0, timePoint.Location())
	overMon := time.Date(timePoint.Year(), timePoint.Month()-1, 1, 0, 0, 0, 0, timePoint.Location())

	count, _ := sql.CountByRange(ctx, month, month.AddDate(0, 1, 0))
	onCount, _ := sql.CountByRange(ctx, onMon, onMon.AddDate(0, 1, 0))
	overCount, _ := sql.CountByRange(ctx, overMon, overMon.AddDate(0, 1, 0))
	return model.Comparison{
		Num:      count.Count,
		OnRate:   calculateRate(count.Count, onCount.Count),
		OverRate: calculateRate(count.Count, overCount.Count),
	}
}

func yearIncrease(ctx context.Context, timePoint time.Time, cache store.ICache, sql store.ICounter) model.Comparison {
	year := time.Date(timePoint.Year(), 1, 1, 0, 0, 0, 0, timePoint.Location())
	lastYear := year.AddDate(-1, 0, 0)
	count, _ := sql.CountByRange(ctx, year, year.AddDate(1, 0, 0))
	overCount, _ := sql.CountByRange(ctx, lastYear, year)
	return model.Comparison{
		Num:      count.Count,
		OverRate: calculateRate(count.Count, overCount.Count),
	}
}

func sumCount(days []int64) int64 {
	var sum int64
	for _, day := range days {
		sum += day
	}
	return sum
}

// 获取从月初到当前时间所有的数据
func dayWave(ctx context.Context, timePoint time.Time, cache store.ICache, sql store.ICounter) model.Wave {
	// 当前月份月初
	ds, _ := sql.ThirtyDaysCount(ctx, timePoint)
	dayCounts := convertToCount(ds)
	return model.Wave{
		Total:    sumCount(dayCounts),
		Quantity: dayCounts,
	}
}

// 获取今年12月份所有的数据，最多12个月 ，最好做一下缓存不存在处理
func monthWave(ctx context.Context, timePoint time.Time, cache store.ICache, sql store.ICounter) model.Wave {
	// 如果月份数据为空
	ms, err := sql.TwelveMonthsCount(ctx, timePoint)
	if err != nil {
		log.Warn("month wave: sql query failed")
		return model.Wave{}
	}
	monCounts := convertToCount(ms)
	if err != nil {
		log.Warn("month wave:redis cache failed")
	}
	return model.Wave{
		Total:    sumCount(monCounts),
		Quantity: monCounts,
	}
}

// 最近5年的数据
func yearWave(ctx context.Context, cache store.ICache, sql store.ICounter) model.Wave {
	// 只缓存前面4年的数据
	sum := func(arr []int64) int64 {
		var s int64
		for _, v := range arr {
			s += v
		}
		return s
	}
	ys, err := sql.FiveYearsCount(ctx, time.Now())
	if err != nil {
		log.Warn("year wave: sql query failed")
		return model.Wave{}
	}
	yearCount := convertToCount(ys)
	if err != nil {
		log.Warn("year wave:cache failed")
	}

	return model.Wave{
		Total:    sum(yearCount),
		Quantity: yearCount,
	}
}

// 获取从月初到当前时间所有的数据
func dayUserWave(ctx context.Context, timePoint time.Time, cache store.ICache, sql store.ICounter) model.Wave {
	// 当前月份月初
	ds, _ := sql.ThirtyDaysCount(ctx, timePoint)
	dayCounts := convertToCount(ds)
	return model.Wave{
		Total: func(count []int64) int64 {
			now := time.Now().Day()
			c := len(count)
			if c == 0 {
				return 0
			}
			return count[now-2]
		}(dayCounts),
		Quantity: dayCounts,
	}
}

// 获取今年12月份所有的数据，最多12个月 ，最好做一下缓存不存在处理
func monthUserWave(ctx context.Context, timePoint time.Time, cache store.ICache, sql store.ICounter) model.Wave {
	// 如果月份数据为空
	ms, err := sql.TwelveMonthsCount(ctx, timePoint)
	if err != nil {
		log.Warn("month wave: sql query failed")
		return model.Wave{}
	}
	monCounts := convertToCount(ms)
	if err != nil {
		log.Warn("month wave:redis cache failed")
	}
	return model.Wave{
		Total: func(count []int64) int64 {
			now := time.Now().Month()
			c := len(count)
			if c == 0 {
				return 0
			}
			return count[now-1]
		}(monCounts),
		Quantity: monCounts,
	}
}

// 最近5年的数据
func yearUserWave(ctx context.Context, cache store.ICache, sql store.ICounter) model.Wave {
	// 只缓存前面4年的数据
	ys, err := sql.FiveYearsCount(ctx, time.Now())
	if err != nil {
		log.Warn("year wave: sql query failed")
		return model.Wave{}
	}
	yearCount := convertToCount(ys)
	if err != nil {
		log.Warn("year wave:cache failed")
	}
	return model.Wave{
		Total: func(count []int64) int64 {
			c := len(count)
			if c == 0 {
				return 0
			}
			return count[c-1]
		}(yearCount),
		Quantity: yearCount,
	}
}

func calculateRate(a, b int64) float32 {
	if a == 0 {
		return 0.0
	}
	if b == 0 {
		return 1.0
	}
	return float32(a-b) / float32(b)
}
